home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / gnuwget.zip / wget-1.4.3 / src / main.c < prev    next >
C/C++ Source or Header  |  1997-02-09  |  15KB  |  552 lines

  1. /* Command line parsing.
  2.    
  3.    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.    
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.    
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19.  
  20. #ifdef HAVE_CONFIG_H
  21. #  include <config.h>
  22. #endif /* HAVE_CONFIG_H */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <ctype.h>
  27. #ifdef HAVE_UNISTD_H
  28. #  include <unistd.h>
  29. #endif /* HAVE_UNISTD_H */
  30. #include <sys/types.h>
  31. #ifdef HAVE_STRING_H
  32. #  include <string.h>
  33. #else
  34. #  include <strings.h>
  35. #endif /* HAVE_STRING_H */
  36. #include <assert.h>
  37. #ifdef HAVE_SIGNAL_H
  38. #include <signal.h>
  39. #endif
  40.  
  41. #include "wget.h"
  42. #include "options.h"
  43. #include "main.h"
  44. #include "utils.h"
  45. #include "url.h"
  46. #include "init.h"
  47. #include "retr.h"
  48. #include "recur.h"
  49. #include "ftp.h"
  50. #include "getopt.h"
  51.  
  52. #ifdef WINDOWS
  53. #  include "wsstartup.h"
  54. #endif
  55.  
  56. extern char *version_string;
  57. extern int errno;
  58.  
  59. struct options opt;
  60.  
  61. int
  62. main(int argc, char *const *argv)
  63. {
  64.    char **url, **t, *new;
  65.    char *usage = "Usage: %s [options] [URL-list]\n";
  66.    int i, c, nurl, status, append_to_log, first_time, dt;
  67.    const char *exec_name;
  68.    char *com, *val;
  69.  
  70.    static struct option long_options[] =
  71.    {
  72.       { "backups", no_argument, NULL, 'b' }, /* undocumented! */
  73.       { "continue", no_argument, NULL, 'c' },
  74.       { "convert-links", no_argument, NULL, 'k' },
  75.       { "debug", no_argument, NULL, 'd' },
  76.       { "email-address", no_argument, NULL, 'E' }, /* undocumented! */
  77.       { "follow-ftp", no_argument, NULL, 14 },
  78.       { "force-hier", no_argument, NULL, 'x' },
  79.       { "force-html", no_argument, NULL, 'F'},
  80.       { "help", no_argument, NULL, 'h' },
  81.       { "ignore-length", no_argument, NULL, 10 },
  82.       { "mirror", no_argument, NULL, 'm' },
  83.       { "no-clobber", no_argument, NULL, 13 },
  84.       { "no-parent", no_argument, NULL, 5 },
  85.       { "passive-ftp", no_argument, NULL, 11 },
  86.       { "quiet", no_argument, NULL, 'q' },
  87.       { "recursive", no_argument, NULL, 'r' },
  88.       { "relative", no_argument, NULL, 'L' },
  89.       { "retr-symlinks", no_argument, NULL, 9 },
  90.       { "save-headers", no_argument, NULL, 's' },
  91.       { "server-response", no_argument, NULL, 'S' },
  92.       { "span-hosts", no_argument, NULL, 'H' },
  93.       { "spider", no_argument, NULL, 4 },
  94.       { "timestamping", no_argument, NULL, 'N' },
  95.       { "verbose", no_argument, NULL, 'v' },
  96.       { "version", no_argument, NULL, 'V' },
  97.       
  98.       { "accept", required_argument, NULL, 'A' },
  99.       { "append-output", required_argument, NULL, 'a' },
  100.       { "base", required_argument, NULL, 'B' },
  101.       { "cache", required_argument, NULL, 'C' },
  102.       { "delete-after", no_argument, NULL, 8 },
  103.       { "directory-prefix", required_argument, NULL, 'P' },
  104.       { "domains", required_argument, NULL, 'D' },
  105.       { "dot-style", required_argument, NULL, 6 },
  106.       { "execute", required_argument, NULL, 'e' },
  107.       { "exclude-directories", required_argument, NULL, 'X' },
  108.       { "exclude-domains", required_argument, NULL, 12 },
  109.       { "glob", required_argument, NULL, 'g' },
  110.       { "header", required_argument, NULL, 3 },
  111.       { "htmlify", required_argument, NULL, 7 },
  112.       { "http-passwd", required_argument, NULL, 2 },
  113.       { "http-user", required_argument, NULL, 1 },
  114.       { "include-directories", required_argument, NULL, 'I' },
  115.       { "input-file", required_argument, NULL, 'i' },
  116.       { "level", required_argument, NULL, 'l' },
  117.       { "no", required_argument, NULL, 'n' },
  118.       { "output-document", required_argument, NULL, 'O' },
  119.       { "output-file", required_argument, NULL, 'o' },
  120.       { "proxy", required_argument, NULL, 'Y' },
  121.       { "quota", required_argument, NULL, 'Q' },
  122.       { "reject", required_argument, NULL, 'R' },
  123.       { "timeout", required_argument, NULL, 'T' },
  124.       { "tries", required_argument, NULL, 't' },
  125.       { "user-agent", required_argument, NULL, 'U' }, /* undocumented! */
  126.       { "use-proxy", required_argument, NULL, 'Y' },
  127.       { "wait", required_argument, NULL, 'w' },
  128.       { 0, 0, 0, 0 }
  129.    };
  130.  
  131.    append_to_log = 0;
  132.    initialize();
  133.  
  134.    /* Construct the name of the executable, without the directory
  135.       part. */
  136.    exec_name = strrchr(argv[0], '/');
  137.    if (!exec_name)
  138.       exec_name = argv[0];
  139.    else
  140.       ++exec_name;
  141.  
  142.    while ((c = getopt_long(argc, argv, "hVqvdksxmNWrHSLcFbEY:g:T:U:O:l:n:i:o:a:t:D:A:R:P:B:e:Q:X:I:w:",
  143.                long_options, (int *)0)) != EOF)
  144.    {
  145.       switch(c)
  146.       {
  147.      /* Options without arguments: */
  148.      case 4:
  149.         setval("spider", "on");
  150.         break;
  151.      case 5:
  152.         setval("noparent", "on");
  153.         break;
  154.      case 8:
  155.         setval("deleteafter", "on");
  156.         break;
  157.      case 9:
  158.         setval("retrsymlinks", "on");
  159.         break;
  160.      case 10:
  161.         setval("ignorelength", "on");
  162.         break;
  163.      case 11:
  164.         setval("passiveftp", "on");
  165.         break;
  166.      case 13:
  167.         setval("noclobber", "on");
  168.         break;
  169.      case 14:
  170.         setval("followftp", "on");
  171.         break;
  172.      case 'b':
  173.         setval("backups", "on");
  174.         break;
  175.      case 'c':
  176.         setval("alwaysrest", "on");
  177.         break;
  178.      case 'd':
  179.         setval("debug", "on");
  180.         break;
  181.      case 'E':
  182.         printf("%s\n", opt.ftp_pass);
  183.         exit(0);
  184.         break;
  185.      case 'F':
  186.         setval("forcehtml", "on");
  187.         break;
  188.      case 'H':
  189.         setval("spanhosts", "on");
  190.         break;
  191.      case 'h':
  192.         printhelp();
  193.         exit(0);
  194.         break;
  195.      case 'k':
  196.         setval("convertlinks", "on");
  197.         break;
  198.      case 'L':
  199.         setval("relativeonly", "on");
  200.         break;
  201.      case 'm':
  202.         setval("mirror", "on");
  203.         break;
  204.      case 'N':
  205.         setval("timestamping", "on");
  206.         break;
  207.      case 'S':
  208.         setval("serverresponse", "on");
  209.         break;
  210.      case 's':
  211.         setval("saveheaders", "on");
  212.         break;
  213.      case 'q':
  214.         setval("quiet", "on");
  215.         break;
  216.      case 'r':
  217.         setval("recursive", "on");
  218.         break;
  219.      case 'V':
  220.         printf("%s\n", version_string);
  221.         exit(0);
  222.         break;
  223.      case 'v':
  224.         setval("verbose", "on");
  225.         break;
  226.      case 'x':
  227.         setval("dirstruct", "on");
  228.         break;
  229.  
  230.         /* Options accepting an argument: */
  231.      case 1:
  232.         setval("httpuser", optarg);
  233.         break;
  234.      case 2:
  235.         setval("httppasswd", optarg);
  236.         break;
  237.      case 3:
  238.         setval("header", optarg);
  239.         break;
  240.      case 6:
  241.         setval("dotstyle", optarg);
  242.         break;
  243.      case 7:
  244.         setval("htmlify", optarg);
  245.         break;
  246.      case 12:
  247.         setval("excludedomains", optarg);
  248.         break;
  249.      case 'A':
  250.         setval("accept", optarg);
  251.         break;
  252.      case 'a':
  253.         setval("logfile", optarg);
  254.         append_to_log = 1;
  255.         break;
  256.      case 'B':
  257.         setval("basehref", optarg);
  258.         break;
  259.      case 'C':
  260.         setval("cache", optarg);
  261.         break;
  262.      case 'D':
  263.         setval("domains", optarg);
  264.         break;
  265.      case 'e':
  266.         if (parse_line((unsigned char *)optarg,
  267.                (unsigned char **)&com, (unsigned char **)&val))
  268.         {
  269.            if (!setval(com, val))
  270.           exit(1);
  271.            free(com);
  272.            free(val);
  273.         }
  274.         else
  275.         {
  276.            fprintf(stderr, "%s: invalid command (try --help)\n", optarg);
  277.            exit(1);
  278.         }
  279.         break;
  280.      case 'g':
  281.         setval("glob", optarg);
  282.         break;
  283.      case 'I':
  284.         setval("includedirectories", optarg);
  285.         break;
  286.      case 'i':
  287.         setval("input", optarg);
  288.         break;
  289.      case 'l':
  290.         setval("reclevel", optarg);
  291.         break;
  292.      case 'n':
  293.         for (i = 0; i < strlen(optarg); i++)
  294.            switch(optarg[i])
  295.            {
  296.           case 'v':
  297.              setval("verbose", "off");
  298.              break;
  299.           case 'h':
  300.              setval("simplehostcheck", "on");
  301.              break;
  302.           case 'H':
  303.              setval("addhostdir", "off");
  304.              break;
  305.           case 'd':
  306.              setval("dirstruct", "off");
  307.              break;
  308.           case 'c':
  309.              setval("noclobber", "on");
  310.              break;
  311.           case 'r':
  312.              setval("removelisting", "off");
  313.              break;
  314.           case 'p':
  315.              setval("noparent", "on");
  316.              break;
  317.           default:
  318.              printf("-n%c option is unknown. Try %s -h.\n", optarg[i],
  319.                 exec_name);
  320.              exit(1);
  321.            }
  322.         break;
  323.      case 'O':
  324.         setval("outputdocument", optarg);
  325.         break;
  326.      case 'o':
  327.         setval("logfile", optarg);
  328.         break;
  329.      case 'P':
  330.         setval("dirprefix", optarg);
  331.         break;
  332.      case 'Q':
  333.         setval("quota", optarg);
  334.         break;
  335.      case 'R':
  336.         setval("reject", optarg);
  337.         break;
  338.      case 'T':
  339.         setval("timeout", optarg);
  340.         break;
  341.      case 't':
  342.         setval("numtries", optarg);
  343.         break;
  344.      case 'U':
  345.         setval("useragent", optarg);
  346.         break;
  347.      case 'w':
  348.         setval("wait", optarg);
  349.         break;
  350.      case 'X':
  351.         setval("excludedirectories", optarg);
  352.         break;
  353.      case 'Y':
  354.         setval("useproxy", optarg);
  355.         break;
  356.  
  357.      case '?':
  358.         printf(usage, exec_name);
  359.         exit(0);
  360.         break;
  361.       }
  362.    }
  363.    if (opt.verbose == -1)
  364.       opt.verbose = !opt.quiet;
  365.  
  366.    /* Sanity checks. */
  367.    if (opt.verbose && opt.quiet)
  368.    {
  369.       printf("Can't be verbose and quiet at the same time.\n");
  370.       printf(usage, exec_name);
  371.       exit(1);
  372.    }
  373.    if (opt.timestamping && opt.noclobber)
  374.    {
  375.       printf("Can't timestamp and not clobber old files at the same time.\n");
  376.       printf(usage, exec_name);
  377.       exit(1);
  378.    }
  379.    nurl = argc - optind;
  380.    if (!nurl && !opt.input_filename)
  381.    {
  382.       /* No URL specified. */
  383.       printhelp();
  384.       exit(1);
  385.    }
  386.    /* Allocate basic pointer. */
  387.    url = (char **)nmalloc((nurl + 1) * sizeof(char *));
  388.    /* Fill in the arguments. */
  389.    for (i = 0; i < nurl; i++, optind++)
  390.       url[i] = nstrdup(argv[optind]);
  391.    url[i] = NULL;
  392.  
  393. /* Change the title of console window on win32. */
  394. #ifdef WINDOWS
  395.    ws_changetitle(nurl, url);
  396. #endif
  397.  
  398.    /* Open log filename. */
  399.    if (opt.lfilename)
  400.    {
  401.       opt.lfile = fopen(opt.lfilename, append_to_log ? "a" : "w");
  402.       if (opt.lfile == NULL)
  403.       {
  404.      perror(opt.lfilename);
  405.      exit(1);
  406.       }
  407.    }
  408.    else
  409.       opt.lfile = stdout;
  410.    /* Change the buffering. */
  411.    setbuf(opt.lfile, NULL);
  412. #ifdef DEBUG
  413.    if (opt.debug)
  414.       fprintf(opt.lfile, "DEBUG output created by %s on %s.\n\n",
  415.           version_string, OS_TYPE);
  416. #endif
  417.    /* Open the output filename (if necessary). */
  418.    if (opt.output_document)
  419.    {
  420.       if (ISHYPHEN(opt.output_document))
  421.      opt.dfp = stdout;
  422.       else                      /* not ISHYPHEN(...) */
  423.       {
  424.      opt.dfp = fopen(opt.output_document, "wb");
  425.      if (opt.dfp == NULL)
  426.      {
  427.         perror(opt.output_document);
  428.         exit(1);
  429.      }
  430.       }
  431.    } /* opt.output_document */
  432.  
  433. #ifdef WINDOWS
  434.    wsock_startup();
  435. #endif
  436.  
  437.    /* Setup the signal handler. */
  438. #ifdef HAVE_SIGNAL
  439.    signal(SIGHUP, hangup);
  440. #endif
  441.  
  442.    status = RETROK;             /* Initialize it, just-in-case. */
  443.    /* Retrieve the URLs from argument list. */
  444.    for (first_time = 1, t = url; *t; t++)
  445.    {
  446.       char *filename;
  447.       status = retrieve_url(*t, &filename, &new, NULL, &dt);
  448.       if (opt.recursive && status == RETROK && (dt & TEXTHTML))
  449.      status = recursive_retrieve(filename, new ? new : *t,
  450.                      first_time ? RFIRST_TIME : 0);
  451.       if (new)
  452.      free(new);
  453.       if (filename)
  454.      free(filename);
  455.       first_time = 0;
  456.    }
  457.  
  458.    /* And then from the input file (if exists). */
  459.    if (opt.input_filename)
  460.    {
  461.       int count;
  462.       status = retrieve_from_file(opt.input_filename, opt.force_html, &count);
  463.       if (!count && !opt.quiet)
  464.      fprintf(opt.lfile, "No URLs found in %s.\n", opt.input_filename);
  465.    }
  466.    /* Print the downloaded sum. */
  467.    if (!opt.quiet && (opt.recursive || nurl > 1
  468.               || (opt.input_filename && opt.downloaded != 0)))
  469.    {
  470.       fprintf(opt.lfile,
  471.           "\nFINISHED --%s--\nDownloaded: %s bytes in %d files\n",
  472.           time_str(NULL), legible(opt.downloaded), opt.numurls);
  473.       /* Print quota warning, if exceeded. */
  474.       if (opt.quota && opt.downloaded > opt.quota)
  475.      fprintf(opt.lfile, "Download quota (%s bytes) EXCEEDED!\n",
  476.          legible(opt.quota));
  477.    }
  478.    /* Convert all links.  */
  479.    if (opt.convert_links)
  480.    {
  481.       convert_all_links();
  482.    }
  483.    /* Close the log file. */
  484.    fclose(opt.lfile);
  485.    /* Free the local data. */
  486.    free_vec(url);
  487.    /* ...and clean up the global data. */
  488.    cleanup();
  489.    if (status == RETROK)
  490.       return 0;
  491.    else
  492.       return 1;
  493. }
  494.  
  495.  
  496. /* Print the help message. */
  497. void
  498. printhelp(void)
  499. {
  500.    printf("      GNU %s by Hrvoje Niksic <hniksic@srce.hr>\n",
  501.       version_string);
  502.    printf("Options:\n\
  503.       -o --output-file      log messages to logfile\n\
  504.       -i --input-file       read URL-s from file\n\
  505.       -q --quiet            quiet (no output)\n\
  506.       -t --tries            set number of retries per URL (0 to unlimit)\n\
  507.       -r --recursive        recursive web-suck -- use with care!\n\
  508.       -l --level            maximum recursion depth (0 to unlimit)\n\
  509.       -D --domains          comma-separated list of domains to accept\n\
  510.       -A --accept           comma-separated list of extensions to accept\n\
  511.       -R --reject           comma-separated list of extensions to reject\n\
  512.       -c --continue-ftp     restart getting an existing file\n\
  513. Refer to the info documentation for a complete list of options.\n\
  514. Mail bug reports to <bug-wget@prep.ai.mit.edu>.\n\
  515. Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.\n\n\
  516. This program is distributed in the hope that it will be useful,\n\
  517. but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
  518. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
  519. GNU General Public License for more details.\n");
  520. }
  521.  
  522. /* Hangup signal handler. When wget receives hangup, it will proceed
  523.    operation as usual, trying to write into a log file. If that is
  524.    impossible, the output will be turned off. */
  525.  
  526. #ifdef HAVE_SIGNAL
  527. RETSIGTYPE
  528. hangup(int sig)
  529. {
  530.    char *logname;
  531.    int count;
  532.    
  533.    signal(SIGHUP, hangup);
  534.    if (opt.lfile != stdout)
  535.       return;
  536.    for (count = 0; (logname = unique_name(DEFAULT_LOGFILE, count)) == NULL;
  537.     count++)
  538.       ;
  539.    opt.lfile = fopen(logname, "w");
  540.    if (opt.lfile == NULL)
  541.    {
  542.       printf("%s: %s\n", logname, mystrerror(errno));
  543.       opt.lfile = fopen("/dev/null", "w");
  544.       assert(opt.lfile != NULL);
  545.    }
  546.    /* Change the buffering. */
  547.    setbuf(opt.lfile, NULL);
  548.    printf("SIGHUP received, redirecting output to %s.\n", logname);
  549.    free(logname);
  550. }
  551. #endif /* HAVE_SIGNAL */
  552.